import * as THREE from 'three';
// 导入 轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import * as dat from 'dat.gui'

// 导入物理引擎
import * as CANNON from 'cannon-es'
/**
 *  目标：添加作用力
 */



// 创建场景
const scene = new THREE.Scene();

// 创建相机 fov（角度）, aspect （宽高比）, near 近裁剪面，far 远裁剪面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.set(0, 20, 20)
scene.add(camera);

// 创建物理世界
const world = new CANNON.World({gravity:new CANNON.Vec3(0,-9.8,0)});

// 添加物体
// 创建球和平面
const cubeArr = []
const cubePhysicsMaterial = new CANNON.Material("cubePhysicsMaterial")
function addCube(){
    const cubeGeometry = new THREE.BoxGeometry(1,1,1);
    const cubeMaterial = new THREE.MeshStandardMaterial({ color: 0xffff00 });
    const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    cube.position.set(0,0,0)
    cube.castShadow = true
    scene.add(cube);

    // 创建物理
    const cubePhysics = new CANNON.Box(new CANNON.Vec3(.5,.5,.5))

    const cubeBody = new CANNON.Body({
        shape:cubePhysics,
        // 质量
        mass:1,
        // 材质
        material:cubePhysicsMaterial
    })
    cubeBody.position.set(0, 0, 0)
    world.addBody(cubeBody)

        // 添加作用力
        cubeBody.applyLocalForce(
            // 增加力的方向
            new CANNON.Vec3(180,0,0),
            // 增加力所在到位置
            new CANNON.Vec3(0,0,0) 
        )

        

    cubeArr.push({geometry:cube,physics:cubeBody})
}

addCube()




const floorGeometry = new THREE.PlaneGeometry(20, 20);
const floorMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff ,side:THREE.DoubleSide});
const floor = new THREE.Mesh(floorGeometry, floorMaterial);

floor.position.set(0,-5,0)
floor.rotation.x = -Math.PI / 2
floor.receiveShadow  = true
scene.add(floor);






// 创建物理平面
const floorPhysics = new CANNON.Plane()
const floorBody = new CANNON.Body()
floorBody.mass = 0
floorBody.addShape(floorPhysics)
floorBody.position.set(0,-5,0)

const floorPhysicsMaterial = new CANNON.Material("floorPhysicsMaterial")
// 旋转地面 从垂直 旋转到 水平
floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2)
floorBody.material = floorPhysicsMaterial
world.addBody(floorBody)

// 添加 2种材质碰撞的参数
const defaultContactMaterial = new CANNON.ContactMaterial(
    cubePhysicsMaterial,floorPhysicsMaterial,{
        friction:0.1,//摩擦力
        restitution:0.7,//弹性
    }
)
// 设置材料关联的
// world.addContactMaterial(defaultContactMaterial)

// 设置默认关联的材料
world.defaultContactMaterial = defaultContactMaterial


// 添加环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

// 添加方向光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(3, 3, 3);
directionalLight.castShadow = true;

scene.add(directionalLight)

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);


// 将 webgl 渲染的 canvas 添加到 body 中
document.body.appendChild(renderer.domElement);

// 设置相机 和 场景 通过渲染器渲染
// renderer.render(scene,camera)

// 创建轨道控制器 (相机,用于渲染的dom)
const controls = new OrbitControls(camera, renderer.domElement);

renderer.shadowMap.enabled = true;

// 开启阻尼
controls.enableDamping = true;

// 添加坐标辅助器
const axesHelper = new THREE.AxesHelper(3);
scene.add( axesHelper );

// 设置 clock
const clock = new THREE.Clock();


/**
 * 渲染函数
 * L = V*T   距离 = 速度 * 时间
 */
function render() {

    // 设置世界渲染步数
    world.step(1/120, clock.getDelta())

    cubeArr.forEach(it=>{
        // 位置同步
        it.geometry.position.copy(it.physics.position)
        // 旋转同步
        it.geometry.quaternion.copy(it.physics.quaternion)
    })
    // cube.position.copy(cubeBody.position)

    controls.update()
    renderer.render(scene, camera)
    
    // 浏览器自带的 请求动画帧的方法 ，这里设置 没一帧都调用一下 render 函数
    requestAnimationFrame(render)
}
render();

// 监听窗口大小变化
window.addEventListener('resize', onWindowResize, false);

function onWindowResize() {
    // 重新设置相机的宽高比
    camera.aspect = window.innerWidth / window.innerHeight;
    // 重新设置相机的裁剪面(投影矩阵)
    camera.updateProjectionMatrix();

    // 更新渲染器
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 设置渲染器的像素比
    renderer.setPixelRatio(window.devicePixelRatio);
}

window.addEventListener("mousedown",(e)=>{
    addCube()  
})